'''
Created on Nov 12, 2009

@author: Hatem Oraby
'''
#import sys #Note: sys has to be imported here, not imported inside module so
           # that it work right as it should
from interfaces import moduleHandler
from simManager import Module
from twistedSim import simSetup

class BaseHandler(moduleHandler):
    
    def preSwitchContext(self, create = False):
        pass
        
    def postSwitchContext(self, create = False):
        pass
        
    def preSwitchOriginal(self, create = False):
        pass
    
    def postSwitchOriginal(self, create = False):
        pass

    def runUntilCurrent(self):
        pass
    
    def timeout(self):
        pass
    
    def preLoad(self):
        pass
    
    def postLoad(self):
        pass
    
    def die(self):
        pass
    
    def setModule(self,module):
        self._module = module

class twistedH (BaseHandler):
    '''A handler for applications using Twisted framework '''
    def __init__(self):
        self._reactor = None #Assigned after first load
        

    def postSwitchContext(self, create = False):
        pass

    def runUntilCurrent(self):
        #Get the reactor of the module about to run
        self._reactor.mainLoop()


    def timeout(self):
        if self._reactor._stopped:
            return  -1
        return self._reactor.timeout()
    
    
    def postSwitchOriginal(self, create = False):
        pass
    
    def preLoad(self):
        '''Stuff to do before loading a new module'''
        simSetup.installSocket()
        simSetup.installTime()
        simSetup.installReactorSelect()
    
    
    def postLoad(self):
        '''Called after the module is called for the first time'''
        import sys
        if sys.modules.has_key('twisted.internet.reactor'):
            self._reactor = sys.modules['twisted.internet.reactor']
            self._reactor._id = self._module.getNickname()
            #Do the usual timeout check routine, maybe it stopped working
            #right after the first run.     
            #The first run doesn't return the timeout, so we schedule
            #it for safety again, however if we want later to overcome
            #this then we should do: module._timeout = reactor.timout()
            self._module.ImmediateScheduleRaise()
        else:
            print "Module Name: " + str(self._module.getNickname())
            print "No reactor detected."
    
    
class asyncoreH(BaseHandler):
    

    def runUntilCurrent(self):
        self._loop.loop()
    

    def timeout(self):
        return None

    def preSwitchOriginal(self, create = False):
        simSetup.uninstallAsyncore()

    def preLoad(self):
        from twistedSim.override import _asyncore
        _asyncore._timeout = None
        _asyncore._use_poll = None
        _asyncore._map = None
        _asyncore._count = None
        _asyncore.firstRun = True
        _asyncore._poll_fun = None
        
        if not self._module.isProcessBased: #Bad hack and bad design.
            import sys 
            self._tempModules = sys.modules
            sys.modules = self._module._sysModules

    def postSwitchContext(self, create = False):
        if create:
            simSetup.installSocket()
            simSetup.installTime()
            simSetup.installAsyncore()
        else:
            self.postLoad()
        
    def postLoad(self):
        from twistedSim.override import _asyncore
        _timeout = _asyncore._timeout
        _use_poll = _asyncore._use_poll
        _map = _asyncore._map
        _count = _asyncore._count
        _firstRun = _asyncore.firstRun
        _poll_fun = _asyncore._poll_fun
        self._loop = _asyncore.wrapper(_timeout, _use_poll, _map, _count)

        if not self._module.isProcessBased:        
            import sys
            sys.modules = self._tempModules
            

if __name__ == '__main__':
    pass